import sys
import os
import objc
import re

from objc import YES, NO, NULL

UIKit = objc.loadBundle("UIKit", globals(), "/System/Library/Frameworks/UIKit.framework")
objc.loadBundleFunctions(UIKit, globals(), [("UIApplicationMain", "iii@@"),])
_UIApplicationMain = UIApplicationMain
def UIApplicationMain(argv=None, principal=objc.nil, delegate=None):
	if argv == None:
		import sys
		argv = sys.argv
		from ctypes import c_char_p, addressof
		argc = len(argv)
		argv = (c_char_p * argc)(*argv)

		if delegate is None:
			delegate = principal

		if principal != objc.nil:
			principal = NSString.alloc().initWithString_(principal.__name__)
		if delegate != objc.nil:
			delegate = NSString.alloc().initWithString_(delegate.__name__)

		return _UIApplicationMain(argc, addressof(argv), principal, delegate)

class PYApplication(UIApplication):
	currentMenu = 0         #  0 for  Map/Route List - 1 for settings
	path        = None

	ImportAlert = None
	aboutAlert  = None
	instrAlert  = None
	processAlert = None
	
	currentMap      = ''
	currentRoute    = ''
	currentBookmark = ''
	change       = 0        # 0 = no change with current setting , 1 = change was happend
	
	dispMenu     = []       # displayed menu
	settingsMenu = []       # prepared settings menu
	mainMenu     = []       # prepared main menu

	mapItems   = []         # list of Maps
	routeItems = []         # list of Routes
	bookmItems = []         # list of Bookmarks
	cmdItems   = []         # list of Setting Comands

	version_number = "v2.1.2"
	version    = "iPhone Offline Maps " + version_number
	# -------------------------------------------------------------------------------------
	def string(self, s):
		return NSBundle.mainBundle().localizedStringForKey_value_table_(s, "", None)

	# -------------------------------------------------------------------------------------
	@objc.signature("i@:@")
	def numberOfSectionsInTableView_(self, list):
		return len(self.dispMenu)

	@objc.signature("i@:@i")
	def tableView_numberOfRowsInSection_(self, table, section):
		return len(self.dispMenu[section]["items"])

	@objc.signature("i@:@@")
	def tableView_canEditRowAtIndexPath_(self, table,  path):
		# Cells are editable only if the table is in edition mode (prevent delete to appear if user swipe on a row)
		return table.isEditing()

	@objc.signature("@@:@@")
	def tableView_cellForRowAtIndexPath_(self, table,  path):
		cell = table.dequeueReusableCellWithIdentifier_("PYApplication")
		if cell == None:
			zrect = ((0, 0), (0, 0))
			cell =  UITableViewCell.alloc().initWithFrame_reuseIdentifier_(zrect, "PYApplication")

		myLabel = cell.viewWithTag_(10)
		try:
			size = self.dispMenu[path.section()]["items"][path.row()]["info"] 
		except:
			size = None

		cellRect = cell.bounds()
		x = 35
		if self.table.isEditing():
			x = 15
		if myLabel == None:
			myLabel = UILabel.alloc().initWithFrame_((((cellRect[1][0]/3)*2,cellRect[0][1]+5), ((cellRect[1][0]/3)-x,cellRect[1][1]-10)))
			myLabel.setTag_(10)
			myColor = UIColor.alloc().initWithRed_green_blue_alpha_(0.0,0.141,0.588,1)
			myLabel.setTextColor_(myColor)
			myLabel.setTextAlignment_(2)
			cell.addSubview_(myLabel)

		if size == None:
			myLabel.setFrame_((((cellRect[1][0]/3)*3,cellRect[0][1]+5), ((cellRect[1][0]/3)-x,cellRect[1][1]-10)))
		else:
			myLabel.setFrame_((((cellRect[1][0]/3)*2,cellRect[0][1]+5), ((cellRect[1][0]/3)-x,cellRect[1][1]-10)))
			myLabel.setText_(size + " ")

		if self.currentMenu == 0:
			cell.setAccessoryType_(1)
		else:
			cell.setAccessoryType_(0)

		try:
			pathway = self.dispMenu[path.section()]["items"][path.row()]["fullname"] 
			print pathway
			print len(pathway)
		except:
			pathway = None
		# here must be change to recheck the configure file data    
		if (self.currentMenu == 0) and (pathway != None) and ((self.currentMap == pathway) or (self.currentBookmark == pathway) or (self.currentRoute == pathway)):
			cell.setTextColor_(UIColor.alloc().initWithRed_green_blue_alpha_(0.75,0,0,1))
		else:
			cell.setTextColor_(UIColor.blackColor())

		cell.setText_(self.dispMenu[path.section()]["items"][path.row()]["name"])
		return cell

	@objc.signature("@@:@i")
	def tableView_titleForHeaderInSection_(self, table, section):
		return self.string(self.dispMenu[section]["section"])

	# (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
	@objc.signature("v@:@@")
	def tableView_didSelectRowAtIndexPath_(self, table, path):
		self.path = path

		select = self.path.section()
		row    = self.path.row()

		# in edition mode, first row is for import
		if (table.isEditing() == True) and (row == 0):
			self.iomsDisplayImportAlert(path.section())
			return

		section = self.dispMenu[ select ]["section"]
		if section == "Infos":
			title  = self.dispMenu[ select ]["items"][row]["name"]

			if title == self.string("About"):
				self.aboutAlert.show()
			elif title == self.string("Update"):
				self.iomsDisplayAlert(self.string("Update"),self.string("Update_Message"))
			else:
				self.instrAlert.show()

		else:
			alert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(None, None, self, self.string("Cancel"), None)

			if section == "Maps":
				alert.setTitle_(self.string("Processing_Map"))
				alert.setMessage_(self.string("Processing_Map_Message") % (self.dispMenu[ select ]["items"][row]["name"] , self.dispMenu[ select ]["items"][row]["info"]) )
				alert.addButtonWithTitle_(self.string("Link"))
				alert.addButtonWithTitle_(self.string("Copy"))

				progressFrame = ((25, 15), (25.0, 25.0))
				progressView1 = UIActivityIndicatorView.alloc().initWithFrame_(progressFrame)
				progressView1.setActivityIndicatorViewStyle_(0)
				progressView1.startAnimating()
				progressView1.setTag_(21)

				progressFrame = ((230, 15), (25.0, 25.0))
				progressView2 = UIActivityIndicatorView.alloc().initWithFrame_(progressFrame)
				progressView2.setActivityIndicatorViewStyle_(0)
				progressView2.startAnimating()
				progressView2.setTag_(22)

				alert.addSubview_(progressView1)
				alert.addSubview_(progressView2)
			elif section == "Routes":
				alert.setTitle_(self.string("Processing_Route"))
				alert.setMessage_(self.string("Processing_Route_Message") % self.dispMenu[ select ]["items"][row]["name"] )
				alert.addButtonWithTitle_(self.string("Copy"))
			elif section == "Bookmarks":
				alert.setTitle_(self.string("Processing_Bookmarks"))
				alert.setMessage_(self.string("Processing_Bookmarks_Message") % self.dispMenu[ select ]["items"][row]["name"] )
				alert.addButtonWithTitle_(self.string("Copy"))
			elif section == "Cache Management":
				alert.setTitle_(self.string("Processing_Command"))
				alert.setMessage_(self.string("Processing_Command_Message") % self.dispMenu[ select ]["items"][row]["name"] )
				alert.addButtonWithTitle_(self.string("Ok"))

			alert.show()

	# (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
	@objc.signature("i@:@@")
	def tableView_editingStyleForRowAtIndexPath_(self, table, path):
		if path == None:
			return 0

		if path.section() != 0 and path.row() == 0:
			return 2
		else:
			return 1

	# (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
	@objc.signature("v@:@i@")
	def tableView_commitEditingStyle_forRowAtIndexPath_(self, table, style, path):
		if self.currentMenu != 0:
			return

		self.path = path        # saving it to make it accessible for delegated funct
		# If row is deleted, remove it from the list.
		if style == 1: 
			#UITableViewCellEditingStyleDelete
			if path.section() == 1:
				# path in Map section
				retval = os.system("rm -fr " + self.mapItems[path.row()]["fullname"])
				if retval == 0:
					self.mapItems.remove(self.mapItems[path.row()])
				else:
					self.iomsDisplayError(self.string("Error_Code") % str(retval))
					return
				# Test if the removed map was the linked one
				if (os.path.islink("/var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb") == True) and (os.path.exists("/var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb") == False):
					# which means the current Maps data is a broken symbolic link , we should delete the broken symbolic link
					os.system("rm /var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb ; rm /var/mobile/Library/Preferences/com.apple.Maps.plist")
					# and clear the badge
					self.setApplicationBadge_(self.string("Clear") ) 
			elif path.section() == 2:
				# path in Route section
				retval = os.system("rm -fr " + self.routeItems[path.row()]["fullname"])
				if retval == 0:
					self.routeItems.remove(self.routeItems[path.row()])
				else:
					self.iomsDisplayError(self.string("Error_Code") % str(retval))
					return
			elif path.section() == 3:
				# path in Bookmark section
				retval = os.system("rm -fr " + self.bookmItems[path.row()]["fullname"])
				if retval == 0:
					self.bookmItems.remove(self.bookmItems[path.row()])
				else:
					self.iomsDisplayError(self.string("Error_Code") % str(retval))
					return

			# adjusting sections title
			if len(self.mapItems) == 1:
				self.mainMenu[1]["section"] = "Maps_Empty"
			if len(self.routeItems) == 1:
				self.mainMenu[2]["section"] = "Routes_Empty"
			if len(self.bookmItems) == 1:
				self.mainMenu[3]["section"] = "Bookmarks_Empty"

			self.table.deleteRowsAtIndexPaths_withRowAnimation_([path], 0)

		elif style == 2: 
			#UITableViewCellEditingStyleInsert
			self.iomsDisplayImportAlert(path.section())

	@objc.signature("v@:@i")
	def alertView_clickedButtonAtIndex_(self, alert, button):

		select = self.path.section()
		row    = self.path.row()

		section = self.dispMenu[ select ]["section"]

		if alert == self.ImportAlert:
			# Import Alert Delegate

			# cancel button
			if button == 0:
				return
			text_input = alert.textField().text()
			if text_input == "":
				# without input the import title.
				self.iomsDisplayAlert(self.string("blank_name"), self.string("blank_name_Message"))
				return

			if section[:9] == "Bookmarks":
				# destination path
				path = self.userHomeDirectory() + "/Media/Maps/Bookmarks"
				destBookmarks = os.path.join(path, text_input)
				defaultBookmark = "/var/mobile/Library/Maps/Bookmarks.plist"
				# if there is no Bookmarks in Maps

				if os.path.exists(destBookmarks):
					self.iomsDisplayAlert(self.string("Bookmarks_exists"), self.string("Bookmarks_exists_Message") % text_input)
					return

				# protecting spaces with '\' to prevent os commands to fail
				destBookmarks = re.sub(r' ', '\ ', destBookmarks)

				retval = os.system("cp " + defaultBookmark+ " " + destBookmarks)
				if retval != 0:
					self.iomsDisplayError(self.string("Error_Action_Code") % str(retval) )
					return

				self.currentBookmark = destBookmarks
				self.change = 1

			elif section[:6] == "Routes":
				# destination path
				path = self.userHomeDirectory() + "/Media/Maps/Routes"
				destRoute = os.path.join(path, text_input)
				defaultRoute = "/var/mobile/Library/Maps/Route.plist"

				if os.path.exists(destRoute):
					self.iomsDisplayAlert(self.string("Route_exists"), self.string("Route_exists_Message") % text_input)
					return

				# protecting spaces with '\' to prevent os commands to fail
				destRoute = re.sub(r' ', '\ ', destRoute)

				retval = os.system("cp " + defaultRoute + " " + destRoute)
				if retval != 0:
					self.iomsDisplayError(self.string("Error_Action_Code") % str(retval) )
					return

				self.currentRoute = destRoute
				self.change = 1

			elif section[:4] == "Maps":
				# destination path
				
				path = self.userHomeDirectory() + "/Media/Maps/Cache"
				destMap = os.path.join(path, text_input)
				defaultMaptitle = "/var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb"
				defaultPlist = "/var/mobile/Library/Preferences/com.apple.Maps.plist"
				if os.path.exists(destMap):
					self.iomsDisplayAlert(self.string("Map_exists"), self.string("Map_exists_Message") % text_input )
					return
				# to avoid the Map data is one of our Maps date which using symbolic link 
				if os.path.islink(defaultMaptitle):
					self.iomsDisplayAlert(self.string("Symbolic_link"),self.string("Symbolic_link_Message"))
					return    

				try:
					os.makedirs(destMap)
				except:
					self.iomsDisplayError(self.string("Error_Creat_Folder") % destMap)
					return

				# protecting spaces with '\' to prevent os commands to fail
				destMap = re.sub(r' ', '\ ', destMap)

				retval1 = os.system("mv " + defaultMaptitle + " " + destMap)
				retval2 = os.system("mv " + defaultPlist    + " " + destMap)

				if (retval1 != 0) or (retval2 != 0):
					self.iomsDisplayError(self.string("Error_Copy_Code") % ( str(retval1) , str(retval2)))
					return
				# Make a symbolic link to the Maps, and avoid people report that is an error , when importing a Maps
				# the Maps goes blank :P
				MapTiles = os.path.join(destMap,"MapTiles.sqlitedb")
				plist    = os.path.join(destMap,"com.apple.Maps.plist")
				os.system("ln -s " + MapTiles + " " + defaultMaptitle )
				os.system("ln -s " + plist    + " " + defaultPlist    )

				# Set current Map to this
				self.currentMap = destMap
				self.change = 1
				# change the badge for this new imported Maps...
				badge = text_input + '   '
				badge = badge[:4]
				self.setApplicationBadge_(badge)

			# Reload Maps List
			self.iomsPrepareItems()
			self.iomsDisplayAlert(self.string("Import_Done"), self.string("Import_Done_Message") % alert.textField().text())

			self.table.setEditing_(False)
			self.iomsDisplayCurrentMenu()
			self.table.reloadData()

		elif alert == self.aboutAlert:
			# cancel button
			if button == 0:
				url = NSURL.alloc().initWithString_("http://code.google.com/p/iphoneofflinemap/")
				UIApplication.sharedApplication().openURL_(url)
				sys.exit()
			else:
				return

		elif alert == self.processAlert:
			# cancel button
			if button == 1:
				UIApplication.sharedApplication().launchApplicationWithIdentifier_suspended_("com.apple.Maps", False)
				sys.exit()
			else:
				return

		else:
			if section == "Infos":
				# cancel button
				if button == 0:
					return

			else:
				if button == 1:
					cmd = self.dispMenu[ select ]["items"][row]["action-1"]
				elif button == 2:
					cmd = self.dispMenu[ select ]["items"][row]["action-2"]
				else:
					return
				retval = os.system(cmd)

				if retval != 0:
					self.iomsDisplayError(self.string("Error_Action_Code") % str(retval))
					return
				if section[:5] == "Cache":
					option = self.dispMenu[ select ]["items"][ row ]["action-2"]
					if option == "1" : # remove all Maps data , delete currentMap 
						self.currentMap = ' '
						self.change = 1
						print "remove all Maps data"
					elif option == "2" : # remove Route data , delete currentRoute
						self.currentRoute = ' '
						self.change = 1
						print "remove Route data"
					elif option == "3" : # remove Bookmarks data , delete currentBookmark
						self.currentBookmark = ' '
						self.change = 1
						print "remove Bookmarks data"
					elif option == "4" : # remove badge , nothing should be deleted...
						# Do nothing....
						print "remove badge"
				elif section[:4] == "Maps" :
					# setup the currentMap
					self.currentMap = self.dispMenu[ select ]["items"][row]["fullname"] 
					self.change = 1
				elif section[:6] == "Routes" :
					# setup the currentRoute
					self.currentRoute = self.dispMenu[ select ]["items"][row]["fullname"] 
					self.change = 1
				elif section[:9] == "Bookmarks" :
					# setup the currentBookmark
					self.currentBookmark = self.dispMenu[ select ]["items"][row]["fullname"] 
					self.change = 1

				if ((self.dispMenu[ select ]["items"][row]["badge"] != None) and ((section[:4] == "Maps") or (section[:5] == "Cache"))):
					self.setApplicationBadge_( self.dispMenu[ select ]["items"][row]["badge"] )
				if section != "Cache Management":
					self.table.reloadData()
					self.processAlert.show()

		if self.change == 1:
			# there must be something change
			self.iomsWriteConfigure()
			self.change = 0

	@objc.signature("v@:@i")
	def navigationBar_buttonClicked_(self,navbar,button):
		self.table.deselectRowAtIndexPath_animated_(self.table.indexPathForSelectedRow(), False)
		if button == 1:
			# left button
			self.table.setEditing_animated_(False, False)

			if self.currentMenu == 0:
				self.currentMenu = 1
			else:
				self.currentMenu = 0
			self.iomsDisplayCurrentMenu()
			self.table.reloadData()
		else:
			# right button : edit
			if self.table.isEditing():
				# need to quit edition
				self.navbar.showLeftButton_withStyle_rightButton_withStyle_(self.string("More"), 0, self.string("Edit"), 0)

				# inserting import items
				self.mapItems.remove  ({ "name" : self.string("item_Map_Import") })
 				self.routeItems.remove({ "name" : self.string("item_Route_Import") })
				self.bookmItems.remove({ "name" : self.string("item_Bookmarks_Import") })

			else:
				# start edition
				self.navbar.showLeftButton_withStyle_rightButton_withStyle_(None, 0, self.string("Done"), 2)

				# inserting import items
				self.mapItems.insert  (0, { "name" : self.string("item_Map_Import") })
				self.routeItems.insert(0, { "name" : self.string("item_Route_Import") })
				self.bookmItems.insert(0, { "name" : self.string("item_Bookmarks_Import") })

			self.table.reloadData()
			self.table.setEditing_animated_(not self.table.isEditing(), False)

	def iomsDisplayError(self, message):
		UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(self.string("Error"), message, None, self.string("Ok"), None).show()
	# I'm a lazy guy , :P
	def iomsDisplayAlert(self, title , message):
		UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(title, message, None, self.string("Ok"), None).show()

	def iomsDisplayImportAlert(self, func):
		if func == 1:       # Map Import
			if not (os.path.exists("/var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb") and os.path.exists("/var/mobile/Library/Preferences/com.apple.Maps.plist")):
				self.iomsDisplayAlert(self.string("Failed_Import_Map"), self.string("Failed_Import_Map_Message"))
				return

			self.ImportAlert.setTitle_(self.string("Import_Map"))
			self.ImportAlert.setMessage_(self.string("Import_Map_Message"))
			self.ImportAlert.textField().setText_("Maps_" + str(len(self.mapItems)))
		elif func == 2:     # Route Import
			# check for an existing route
			if not os.path.exists("/var/mobile/Library/Maps/Route.plist"):
				self.iomsDisplayAlert(self.string("Failed_Import_Route"), self.string("Failed_Import_Route_Message"))
				return

			self.ImportAlert.setTitle_(self.string("Import_Route"))
			self.ImportAlert.setMessage_(self.string("Import_Route_Message"))
			self.ImportAlert.textField().setText_("Route_" + str(len(self.routeItems)) + ".plist")
		else:               # Bookmark Import
			# check for an existing route
			if not os.path.exists("/var/mobile/Library/Maps/Bookmarks.plist"):
				self.iomsDisplayAlert(self.string("Failed_Import_Bookmarks"), self.string("Failed_Import_Bookmarks_Message"))
				return

			self.ImportAlert.setTitle_(self.string("Import_Bookmarks"))
			self.ImportAlert.setMessage_(self.string("Import_Bookmarks_Message"))
			self.ImportAlert.textField().setText_("Bookmarks_" + str(len(self.bookmItems)) + ".plist")

		self.ImportAlert.show()
            
	def iomsPrepareItems(self):

		# RAZ
		self.settingsMenu = []       # prepared settings menu
		self.mainMenu     = []       # prepared main menu

		self.mapItems   = []         # list of Maps
		self.routeItems = []         # list of Routes
		self.bookmItems = []         # list of Bookmarks
		self.cmdItems   = []         # list of Setting Comands

		# default map
		default_MapTiles = "/var/mobile/Library/Caches/MapTiles/MapTiles.sqlitedb"
		default_plist = "/var/mobile/Library/Preferences/com.apple.Maps.plist"
		# Route Data
		default_Route = "/var/mobile/Library/Maps/Route.plist"
		# Bookmark Data
		default_Bookmark = "/var/mobile/Library/Maps/Bookmarks.plist"

		# Commands
		rm1 = "rm -rf " + default_MapTiles
		rm2 = "rm -rf " + default_plist
		rmR = "rm -rf " + default_Route
		rmB = "rm -rf " + default_Bookmark
		rmcmd = rm1 + ";"+ rm2
		cpcmd = "cp -r "
		lncmd = "ln -s "

		#--- Reading Map List -------------------------------------------------------------------------------
		path = self.userHomeDirectory() + "/Media/Maps/Cache"
		if not os.path.exists( path ):
			os.makedirs( path )

		dir_list = os.listdir( path )
		for name in dir_list:
			fullname = os.path.join( path, name )
			if os.path.isdir( fullname ):
				MapTiles = os.path.join(fullname , "MapTiles.sqlitedb")
				plist    = os.path.join(fullname , "com.apple.Maps.plist")
				if os.path.exists( MapTiles ) and os.path.exists( plist ):     
					# Actually MapTiles is larger than plist , so , I think we can only use Maptiles to represent the size 
					# of the Maps or just counting the Maps folder by using os.path.getsize(fullname).
					size = os.path.getsize( MapTiles ) >> 20
					if size < 0:
						sizeStr = "> 2Gb"
					else:
						sizeStr = str(size) + "Mb"

					# i18n with CJK unicode support , this paragraph maybe not useful in Europe 
					if os.path.exists( os.path.join(fullname , "badge")):# if badge is exists , readin and set to badgename
						localize = open( os.path.join(fullname , "badge") , "r") 
						local_badgename = unicode( localize.readline(),'UTF-8')
						localize.close()
						if local_badgename[0] == u'\ufeff' :
							# this code erase the BOM of the badge file, BOM is an addition character which Notepad.exe 
							# may add at Utf-8 files , and it will cause error in Application badge .
							local_badgename = local_badgename.lstrip( u'\ufeff' ) 
						# In fact , in CJK coding string , it can only show two unicode text at applications badge
						badgename = local_badgename # which will not limited the badge length...
						name = name + " [" + local_badgename + "]"
					else:
						badgename = name + '   '
						badgename = badgename[:4]
						name = name + " [" + badgename + "]"

					# protecting spaces with '\' to prevent os commands to fail
					fullname = re.sub(r' ', '\ ', fullname)
					MapTiles = re.sub(r' ', '\ ', MapTiles)
					plist    = re.sub(r' ', '\ ', plist)

					#Copy Method
					cmd1   = cpcmd + MapTiles + " " + default_MapTiles
					cmd2   = cpcmd + plist    + " " + default_plist
					final_cpcmd    = rmcmd + ";" + cmd1 + ";" + cmd2
					#Link method
					cmd1   = lncmd + MapTiles + " " + default_MapTiles
					cmd2   = lncmd + plist    + " " + default_plist
					final_lncmd    = rmcmd + ";" + cmd1 + ";" + cmd2
					self.mapItems.append({"fullname" : fullname , "name" : name , "badge" : badgename , "info": sizeStr, "action-1" : final_lncmd ,"action-2" : final_cpcmd})

		#--- Reading Route List ------------------------------------------------------------------------------
		path = self.userHomeDirectory() + "/Media/Maps/Routes"
		if not os.path.exists( path ):
			os.makedirs( path )

		dir_list = os.listdir( path )
		for name in dir_list:
			fullname = os.path.join( path, name )
			if os.path.isfile( fullname ):
				# protecting spaces with '\' to prevent os commands to fail
				fullname = re.sub(r' ', '\ ', fullname)

				cmd1   = "rm " +  default_Route + " ;" + cpcmd + fullname + " " + default_Route
				self.routeItems.append({ "fullname" : fullname , "name" : name , "badge" : name ,"action-1" : cmd1 })

		#--- Reading Bookmark List --------------------------------------------------------------------------
		path = self.userHomeDirectory() + "/Media/Maps/Bookmarks"
		if not os.path.exists( path ):
			os.makedirs( path )

		dir_list = os.listdir( path )
		for name in dir_list:
			fullname = os.path.join( path, name )
			if os.path.isfile( fullname ):
				# protecting spaces with '\' to prevent os commands to fail
				fullname = re.sub(r' ', '\ ', fullname)

				cmd1   = "rm " +  default_Bookmark + " ;" + cpcmd + fullname + " " + default_Bookmark
				self.bookmItems.append({ "fullname" : fullname , "name" : name , "badge" : name ,"action-1" : cmd1 })

		# MAIN MENU
		self.mainMenu.append({"section" : "       " +  self.version  , "items" : [] })
		# lists are built, now we display them
		if self.mapItems != []:
			self.mainMenu.append({"section" : "Maps"   , "items" : self.mapItems })
		else:
			self.mainMenu.append({"section" : "Maps_Empty", "items" : self.mapItems })
		if self.routeItems != []:
			self.mainMenu.append({"section" : "Routes" , "items" : self.routeItems })
		else:
			self.mainMenu.append({"section" : "Routes_Empty", "items" : self.routeItems })
		if self.bookmItems != []:
			self.mainMenu.append({"section" : "Bookmarks"   , "items" : self.bookmItems })
		else:
			self.mainMenu.append({"section" : "Bookmarks_Empty", "items" : self.bookmItems })

		# SETTINGS MENU
		self.cmdItems = [	{"name" : self.string("Remove_Map")         , "badge" : self.string("Clear") ,"action-1" : rmcmd   ,"action-2" :"1"}, \
							{"name" : self.string("Remove_Route")       , "badge" : None                 ,"action-1" : rmR     ,"action-2" :"2"}, \
							{"name" : self.string("Remove_Bookmark")    , "badge" : None                 ,"action-1" : rmB     ,"action-2" :"3"}, \
							{"name" : self.string("Remove_Badge")       , "badge" : ""                   ,"action-1" : "true"  ,"action-2" :"4"}]

		# adding cache mgnt commands
		self.settingsMenu.append({"section" : "Cache Management" , "items" : self.cmdItems })
		# adding infos sectio
		self.settingsMenu.append({"section" : "Infos" , \
								"items" : [ {"name" : self.string("Update")      , "message" : self.string("Update_Message") } , \
											{"name" : self.string("Instructions"), "message" : self.string("Instructions_Message") }, \
											{"name" : self.string("About")       , "message" : (self.string("About_Message") % self.version_number)} ] } )

	def iomsInit(self):
		print self.version
		print "--------------------------"
		#--- Test OfflineMaps default folder ----------------------------------------------------------------
		path = self.userHomeDirectory() + "/Media/Maps"
		if not os.path.exists( path ):
			os.makedirs( path )
		if not os.path.exists('/var/mobile/Media/Maps/ioms.cfg'):
			# new user or just upgrade from previous versions , so we create a new configure file for them
			print "First time Running This Program"
			self.iomsWriteConfigure()
			self.iomsDisplayAlert(self.string("Instructions"),self.string("Instructions_Message"))
		else:
			file = open('/var/mobile/Media/Maps/ioms.cfg','r+')
			version = file.readline().rstrip('\n')
			self.currentMap = file.readline().rstrip('\n') 			# first line for the current Maps
			self.currentRoute = file.readline().rstrip('\n') 		# second line for the current Route
			self.currentBookmark = file.readline().rstrip('\n')		# third line for the current Bookmark
			file.close()

			print "ioms.cfg"
			print 'currentMap      : %s' % self.currentMap
			print 'currentRoute    : %s' % self.currentRoute
			print 'currentBookmark : %s' % self.currentBookmark
			print len(self.currentBookmark)

			if version != self.version :
				# if the version is not correct , show the update message
				print "Program Update"
				print 'configure version %s' % version
				print 'system version %s' % self.version
				self.iomsDisplayAlert(self.string("Update"),self.string("Update_Message"))
				self.iomsWriteConfigure() # upgrade the version

		# buidling static popups for later use  
		self.aboutAlert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(self.string("About"), (self.string("About_Message") % self.version_number ), self, self.string("Web_Site"), None)
		self.aboutAlert.addButtonWithTitle_(self.string("Ok"))

		self.instrAlert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(self.string("Instructions"), self.string("Instructions_Message") , None, self.string("Ok"), None)

		self.processAlert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(self.string("Process_Finish"), self.string("Process_Finish_Message"), self, self.string("Continue"), None)
		self.processAlert.addButtonWithTitle_(self.string("Launch_Maps"))


		# Import Alert
		self.ImportAlert = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(None, None, self, self.string("Cancel"), None)
		self.ImportAlert.addButtonWithTitle_(self.string("Import"))
		self.ImportAlert.addTextFieldWithValue_label_(None, self.string("Output_Name"))
		self.ImportAlert.textField().setTextAlignment_(1)
		self.ImportAlert.textField().becomeFirstResponder()

		# init menus
		self.iomsPrepareItems()
		self.currentMenu = 0

	def iomsWriteConfigure(self):

		print "Writing ioms.cfg"
		print 'currentMap      : %s' % self.currentMap
		print 'currentRoute    : %s' % self.currentRoute
		print 'currentBookmark : %s' % self.currentBookmark

		file = open('/var/mobile/Media/Maps/ioms.cfg','w')
		file.write("%s\n" % self.version)
		# frist line for the current Map data , second line for the current Route , third line for the Bookmark
		file.write( "%s\n" % self.currentMap ) 
		file.write( "%s\n" % self.currentRoute)
		file.write( "%s\n" % self.currentBookmark)
		file.close()

	def iomsDisplayCurrentMenu(self):
		if self.currentMenu == 0:
			self.dispMenu = self.mainMenu
			navItem = self.navbar.popNavigationItemAnimated_(False)
			navItem.setTitle_(self.string("App_Title"))
			self.navbar.pushNavigationItem_(navItem)
			self.navbar.showLeftButton_withStyle_rightButton_withStyle_(self.string("More"), 0, self.string("Edit"), 0)

			# if len(self.routeItems) + len(self.mapItems) == 0:
				# UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(self.string("Instructions"), self.string("Instructions_Message") , None, self.string("Ok"), None).show()

		else:
			self.dispMenu = self.settingsMenu
			navItem = self.navbar.popNavigationItemAnimated_(False)
			navItem.setTitle_(self.string("More"))
			self.navbar.pushNavigationItem_(navItem)
			self.navbar.showLeftButton_withStyle_rightButton_withStyle_(self.string("Back"), 1, None, 0)

	@objc.signature("v@:@")
	def applicationDidFinishLaunching_(self, unused):
		# init 
		self.iomsInit()

		# init window.
		outer = UIHardware.fullScreenApplicationContentRect()
		self.window = UIWindow.alloc().initWithFrame_(outer)

		self.window.orderFront_(self)
		self.window.makeKey_(self)
		self.window._setHidden_(NO)

		inner = self.window.bounds()
		navsize = UINavigationBar.defaultSize()
		navrect = ((0, 0), (inner[1][0], navsize[1]))

		# init UIView
		self.view = UIView.alloc().initWithFrame_(self.window.bounds())
		self.window.setContentView_(self.view)

		# init Navi-bar
		self.navbar = UINavigationBar.alloc().initWithFrame_(navrect);
		self.view.addSubview_(self.navbar)
		self.navbar.setDelegate_(self)
		self.navbar.enableAnimation()
		self.navbar.setBarStyle_(0)

		navitem = UINavigationItem.alloc().initWithTitle_(self.string("App_Title"))
		self.navbar.pushNavigationItem_(navitem)

		# display menu
		self.iomsDisplayCurrentMenu()

		# init Table View
		lower = ((0, navsize[1]), (inner[1][0], inner[1][1] - navsize[1]));
		table = UITableView.alloc().initWithFrame_style_(lower, 1)

		self.table = table
		self.view.addSubview_(table)
		table.setSeparatorStyle_(1)
		table.setDelegate_(self)
		table.setDataSource_(self)

		table.setAllowsSelectionDuringEditing_(True)

		table.reloadData()

UIApplicationMain( principal = PYApplication )
